package com.tianji.promotion.service.impl;

/**
 * <p>
 * 用户领取优惠券的记录，是真正使用的优惠券信息 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-04-22
/*
 *//*

@Service
@Slf4j
@RequiredArgsConstructor
public class UserCouponServiceImplBase extends ServiceImpl<UserCouponMapper, UserCoupon> implements IUserCouponService {
    private final CouponMapper couponMapper;
    private final StringRedisTemplate redisTemplate;
    private final IExchangeCodeService exchangeCodeService;
    private final RedissonClient redissonClient;
    //private final IUserCouponService self;

    @Override
    public List<UserCoupon> queryByCouponId(Long user, List<Long> couponIds) {

        return this.lambdaQuery()
                .eq(UserCoupon::getUserId,user)
                .in(UserCoupon::getCouponId,couponIds)
                .list();
    }

    @Override
    public void addUserCoupon(Long id) {
        Coupon coupon = couponMapper.selectById(id);
        Long userId = UserContext.getUser();
        //新增条件:1.优惠卷最大发行数量>当前已发行数量 2.用户已领取数量<用户限领数量
        if (coupon == null || coupon.getStatus() != CouponStatus.ISSUING){
            throw new RuntimeException("优惠券不存在或不在发行中");
        }
            */
/*UserCoupon userCoupon = new UserCoupon();
            userCoupon.setUserId(userId);
            userCoupon.setCouponId(id);
            userCoupon.setStatus(UserCouponStatus.UNUSED);
            save(userCoupon);
            coupon.setIssueNum(coupon.getIssueNum()+1);
            couponMapper.updateById(coupon);*//*

        RLock lock = redissonClient.getLock("lock:coupon:uid:" + userId);
        boolean isLock = lock.tryLock();
        if (!isLock){
            throw  new RuntimeException("请求太频繁");
        }
        try{
            // saveUserCouponAndCouponUpdate(userId,coupon,null);
            IUserCouponService userCouponService = (IUserCouponService) AopContext.currentProxy();
            userCouponService.saveUserCouponAndCouponUpdate(userId, coupon, null);
        }finally {
            lock.unlock();
        }
    }
    public void addUserCoupon1(Long id) {
      String key=PromotionConstants.COUPON_CACHE_KEY_PREFIX+id;
        Long userId = UserContext.getUser();
            Coupon coupon=queryCouponByCache(key);
        //新增条件:1.优惠卷最大发行数量>当前已发行数量 2.用户已领取数量<用户限领数量
        */
/*if (coupon == null || coupon.getStatus() != CouponStatus.ISSUING){
            throw new RuntimeException("优惠券不存在或不在发行中");
        }*//*

            */
/*UserCoupon userCoupon = new UserCoupon();
            userCoupon.setUserId(userId);
            userCoupon.setCouponId(id);
            userCoupon.setStatus(UserCouponStatus.UNUSED);
            save(userCoupon);
            coupon.setIssueNum(coupon.getIssueNum()+1);
            couponMapper.updateById(coupon);*//*

        if (coupon == null){
            throw new RuntimeException("优惠券不存在");
        }
        if (coupon.getIssueBeginTime().isAfter(LocalDateTime.now()) || coupon.getIssueEndTime().isBefore(LocalDateTime.now())){
            throw new RuntimeException("优惠券不在发行时间");
        }
        RLock lock = redissonClient.getLock("lock:coupon:uid:" + userId);
        boolean isLock = lock.tryLock();
        if (!isLock){
            throw  new RuntimeException("请求太频繁");
        }
        try{
            // saveUserCouponAndCouponUpdate(userId,coupon,null);
            IUserCouponService userCouponService = (IUserCouponService) AopContext.currentProxy();
            userCouponService.saveUserCouponAndCouponUpdate(userId, coupon, null);
        }finally {
            lock.unlock();
        }
    }

    private Coupon queryCouponByCache(String key) {
        Map<Object, Object> objMap = redisTemplate.opsForHash().entries(key);
        Coupon coupon = new Coupon();
        if (objMap.isEmpty()) {
            return null;
        }
        for (Map.Entry<Object, Object> entry : objMap.entrySet()) {
            switch (entry.getKey().toString()) {
                case "issueBeginTime":
                    coupon.setIssueBeginTime(LocalDateTime.parse(entry.getValue().toString()));
                    break;
                case "issueEndTime":
                    coupon.setIssueEndTime(LocalDateTime.parse(entry.getValue().toString()));
                    break;
                case "totalNum":
                    coupon.setTotalNum(Integer.parseInt(entry.getValue().toString()));
                    break;
                case"issueNum":
            }
        }
        return  coupon;
    }

    @Transactional
    public void saveUserCouponAndCouponUpdate(Long userId, Coupon coupon,Long parsedCode) {
        //新增条件:1.优惠卷最大发行数量>当前已发行数量 2.用户已领取数量<用户限领数量
        Integer count = lambdaQuery()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getCouponId, coupon.getId()).count();
        boolean flag = coupon.getTotalNum() > coupon.getIssueNum() && count < coupon.getUserLimit();
        if (!flag){
            throw new RuntimeException("优惠券已领完");
        }
        int i = couponMapper.incrIssueNum(coupon.getId());//更新优惠券发行数量 issue_num++
        if (i!=1){
            throw new RuntimeException("优惠券已领完");
        }
        saveUserCoupon(userId, coupon);//增加用户优惠券
        if (parsedCode!=null){
            //更新兑换码状态
            exchangeCodeService.lambdaUpdate()
                    .set(ExchangeCode::getUserId, userId)
                    .set(ExchangeCode::getStatus, ExchangeCodeStatus.USED)
                    .eq(ExchangeCode::getId, parsedCode)
                    .update();
        }
    }
    @Transactional
    public void saveUserCouponAndCouponUpdate1(Long userId, Coupon coupon,Long parsedCode) {
        //新增条件:1.优惠卷最大发行数量>当前已发行数量 2.用户已领取数量<用户限领数量
        */
/*Integer count = lambdaQuery()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getCouponId, coupon.getId()).count();*//*

        //将用户优惠券信息保存到redis中，++
        Long increment = redisTemplate.opsForHash().increment(PromotionConstants.USER_COUPON_CACHE_KEY_PREFIX + coupon.getId(), userId.toString(), 1);

        boolean flag = coupon.getTotalNum() > coupon.getIssueNum() && increment < coupon.getUserLimit();
        if (!flag){
            throw new RuntimeException("优惠券已领完");
        }
        //更新优惠券发行数量 issue_num++
        redisTemplate.opsForHash().increment(PromotionConstants.COUPON_CACHE_KEY_PREFIX + coupon.getId(), "issueNum", 1);
        */
/**
         * 可以将这段db操作通过mq进行优化
        * *//*


        int i = couponMapper.incrIssueNum(coupon.getId());//更新优惠券发行数量 issue_num++
        if (i!=1){
            throw new RuntimeException("优惠券已领完");
        }
        saveUserCoupon(userId, coupon);//增加用户优惠券
        if (parsedCode!=null){
            //更新兑换码状态
            exchangeCodeService.lambdaUpdate()
                    .set(ExchangeCode::getUserId, userId)
                    .set(ExchangeCode::getStatus, ExchangeCodeStatus.USED)
                    .eq(ExchangeCode::getId, parsedCode)
                    .update();
        }
    }

    @Override
    public PageDTO<CouponPageVO> queryMyCouponPage(UserCouponQuery query) {
        //获取当前登录用户id
        Long userId = UserContext.getUser();
        Page<UserCoupon> page = lambdaQuery()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getStatus, query.getStatus())
                .page(query.toMpPage("term_end_time", true));
        List<UserCoupon> records = page.getRecords();
        if (CollUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }
        //获取couponIds集合
        List<Long> couponIds = records.stream().map(UserCoupon::getCouponId).collect(Collectors.toList());
        List<Coupon> coupons = couponMapper.selectBatchIds(couponIds);
        List<CouponPageVO> list = BeanUtil.copyToList(coupons, CouponPageVO.class);
        return PageDTO.of(page, list);
    }

    private void saveUserCoupon(Long userId, Coupon coupon) {
        UserCoupon userCoupon = new UserCoupon();
        if (coupon.getTermDays()!=null){
            userCoupon.setTermBeginTime(LocalDateTime.now());
            userCoupon.setTermEndTime(LocalDateTime.now().plusDays(coupon.getTermDays()));
        }else {
            userCoupon.setTermBeginTime(coupon.getTermBeginTime());
            userCoupon.setTermEndTime(coupon.getTermEndTime());
        }
        userCoupon.setUserId(userId);
        userCoupon.setCouponId(coupon.getId());
        userCoupon.setStatus(UserCouponStatus.UNUSED);
        save(userCoupon);
    }
    @Override
    public void exchangeCoupon(String code) {
        if (code==null){
            throw  new BizIllegalException("优惠券兑换码不能为空");
        }
        //解析验证码，得到自增id
        long parsedCode = CodeUtil.parseCode(code);
        //根据bitMap中的返回值判断该兑换码是否被使用过，返回true代表使用过
        Boolean aBoolean = redisTemplate.opsForValue().setBit(PromotionConstants.COUPON_CODE_MAP_KEY, parsedCode, true);
        if (BooleanUtil.isTrue(aBoolean)){
            throw new BizIllegalException("优惠券兑换码已被使用过");
        }
        try {
            //查询db，判断该优惠卷是否存在
            ExchangeCode byId = exchangeCodeService.getById(parsedCode);
            if (byId==null){
                throw new BizIllegalException("优惠券兑换码不存在");
            }
            //查询db，判断该优惠卷是否以及开始兑换或者过期
            if (byId.getExpiredTime().isBefore(LocalDateTime.now())){
                throw new BizIllegalException("优惠券兑换码已过期");
            }
            if (byId.getStatus()!= ExchangeCodeStatus.UNUSED){
                throw new BizIllegalException("优惠券兑换码已被使用过");
            }
            Coupon coupon = couponMapper.selectById(byId.getExchangeTargetId());

            RLock lock = redissonClient.getLock("lock:exchange:coupon:codeId:" + parsedCode);
            boolean isLock = lock.tryLock();
            if (!isLock){
                throw  new RuntimeException("请求太频繁");
            }
            try{
                // saveUserCouponAndCouponUpdate(userId,coupon,null);
                IUserCouponService userCouponService = (IUserCouponService) AopContext.currentProxy();
                userCouponService.saveUserCouponAndCouponUpdate(UserContext.getUser(),coupon,parsedCode);
            }finally {
                lock.unlock();
            }

        } catch (BizIllegalException e) {
            log.error("优惠券兑换码兑换失败，原因：{}",e.getMessage());
            redisTemplate.opsForValue().setBit(PromotionConstants.COUPON_CODE_MAP_KEY, parsedCode, false);
            throw new RuntimeException(e);
        }
    }
}
*/
